package util;

import constant.ChildWindowConstant;
import constant.Constant;
import entity.DataSourceModel;
import entity.Parameters;
import entity.TableConfigModel;

import javax.swing.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName ConfigUtil
 * @Author zrx
 * @Date 2021/11/22 11:59
 */
public class ConfigUtil {

	/**
	 * 保存配置
	 *
	 * @param parameters
	 */
	public static void saveConfig(Parameters parameters) {
		try {
			createFile(Constant.parametersPath);
			createFile(Constant.tableConfigPath);
			//序列化参数对象
			serialization(parameters, Constant.parametersPath);
			//序列化表相关配置
			TableConfigModel tableConfigModel = new TableConfigModel();
			//removeNotExitKey();
			tableConfigModel.setPrimaryKeyListMap(ChildWindowConstant.primaryKeyListMap);
			tableConfigModel.setColumnMsgMap(ChildWindowConstant.columnMsgMap);
			tableConfigModel.setUpdateColumnMsgMap(ChildWindowConstant.updateColumnMsgMap);
			tableConfigModel.setQueryColumnMsgMap(ChildWindowConstant.queryColumnMsgMap);
			tableConfigModel.setAllColumnMsgMap(ChildWindowConstant.allColumnMsgMap);
			tableConfigModel.setCurrentTableCnNameMap(ChildWindowConstant.currentTableCnNameMap);
			tableConfigModel.setTableParamConfig(ChildWindowConstant.tableParamConfig);
			tableConfigModel.setCurrentTableNameAndTypes(ChildWindowConstant.currentTableNameAndTypes);
			tableConfigModel.setTablesQueryMap(ChildWindowConstant.tablesQueryMap);
			tableConfigModel.setTablesQueryEndAndCnMap(ChildWindowConstant.tablesQueryEndAndCnMap);
			tableConfigModel.setMakeEntityModelMap(ChildWindowConstant.makeEntityModelMap);
			tableConfigModel.setMakeEntityEngAndCn(ChildWindowConstant.makeEntityEngAndCn);
			tableConfigModel.setUser1(ChildWindowConstant.user1);
			tableConfigModel.setUser2(ChildWindowConstant.user2);
			tableConfigModel.setUser3(ChildWindowConstant.user3);
			tableConfigModel.setCommonParametersModel(ChildWindowConstant.commonParametersModel);
			tableConfigModel.setDynamicUserList(ChildWindowConstant.dynamicUserList);
			tableConfigModel.setDataSourceModelMap(ChildWindowConstant.dataSourceModelMap);
			serialization(tableConfigModel, Constant.tableConfigPath);
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, "保存配置时出错（不影响正常使用，只是下次需要重新配置）！" + e.getMessage(), "警告", JOptionPane.WARNING_MESSAGE);
		}

	}

	public static void removeNotExitKey() {
		ChildWindowConstant.dataSourceModelMap.forEach((k, v) -> {
			String[] modeNameArr = v.getTableName().split("#");
			removeNotExistKeyByKeyArr(v.getPrimaryKeyListMap(), modeNameArr);
			removeNotExistKeyByKeyArr(v.getColumnMsgMap(), modeNameArr);
			removeNotExistKeyByKeyArr(v.getUpdateColumnMsgMap(), modeNameArr);
			removeNotExistKeyByKeyArr(v.getQueryColumnMsgMap(), modeNameArr);
			removeNotExistKeyByKeyArr(v.getAllColumnMsgMap(), modeNameArr);
			removeNotExistKeyByKeyArr(v.getCurrentTableCnNameMap(), modeNameArr);
			removeNotExistKeyByKeyArr(v.getCurrentTableNameAndTypes(), modeNameArr);
		});
	}

	/**
	 * 根据key数组移除map中不存在数组中的元素
	 *
	 * @param map
	 * @param keyArr
	 */
	private static <T> Map<String, T> removeNotExistKeyByKeyArr(Map<String, T> map, String[] keyArr) {
		Set<String> notExistKey = map.keySet().stream().filter(key -> !Arrays.asList(keyArr).contains(key)).collect(Collectors.toSet());
		notExistKey.forEach(map::remove);
		return map;
	}

	/**
	 * 读取上次的配置
	 *
	 * @return
	 */
	public static Parameters readConfig() {
		Parameters parameters = null;
		try {
			parameters = deserialization(Constant.parametersPath);
			TableConfigModel tableConfigModel = deserialization(Constant.tableConfigPath);
			if (tableConfigModel != null) {
				//兼容之前的配置
				if (parameters != null && tableConfigModel.getDataSourceModelMap() == null) {
					DataSourceModel dataSourceModel = new DataSourceModel();
					parameters.setDataSourceName("db1");
					dataSourceModel.setDataSourceName("db1");
					dataSourceModel.setDataBaseTypeVal(parameters.getDataBaseTypeVal());
					dataSourceModel.setDataBaseIpVal(parameters.getDataBaseIpVal());
					dataSourceModel.setDataBasePortVal(parameters.getDataBasePortVal());
					dataSourceModel.setDataBasePwdVal(parameters.getDataBasePwdVal());
					dataSourceModel.setDataBaseNameVal(parameters.getDataBaseNameVal());
					dataSourceModel.setDataBaseUserNameVal(parameters.getDataBaseUserNameVal());
					dataSourceModel.setDataBaseUrl(parameters.getDataBaseUrl());
					dataSourceModel.setDataBaseDriverClass(parameters.getDataBaseDriverClass());
					dataSourceModel.setTableName(parameters.getTableName());
					dataSourceModel.setPrimaryKeyListMap(tableConfigModel.getPrimaryKeyListMap());
					dataSourceModel.setColumnMsgMap(tableConfigModel.getColumnMsgMap());
					dataSourceModel.setUpdateColumnMsgMap(tableConfigModel.getUpdateColumnMsgMap());
					dataSourceModel.setQueryColumnMsgMap(tableConfigModel.getQueryColumnMsgMap());
					dataSourceModel.setAllColumnMsgMap(tableConfigModel.getAllColumnMsgMap());
					dataSourceModel.setCurrentTableCnNameMap(tableConfigModel.getCurrentTableCnNameMap());
					dataSourceModel.setTableParamConfig(tableConfigModel.getTableParamConfig());
					dataSourceModel.setTablesQueryMap(tableConfigModel.getTablesQueryMap());
					dataSourceModel.setTablesQueryEndAndCnMap(tableConfigModel.getTablesQueryEndAndCnMap());
					ChildWindowConstant.dataSourceModelMap.put("db1", dataSourceModel);
					tableConfigModel.setDataSourceModelMap(ChildWindowConstant.dataSourceModelMap);
				}
				ChildWindowConstant.primaryKeyListMap = tableConfigModel.getPrimaryKeyListMap();
				ChildWindowConstant.columnMsgMap = tableConfigModel.getColumnMsgMap();
				ChildWindowConstant.updateColumnMsgMap = tableConfigModel.getUpdateColumnMsgMap();
				ChildWindowConstant.queryColumnMsgMap = tableConfigModel.getQueryColumnMsgMap();
				ChildWindowConstant.allColumnMsgMap = tableConfigModel.getAllColumnMsgMap();
				ChildWindowConstant.currentTableCnNameMap = tableConfigModel.getCurrentTableCnNameMap();
				ChildWindowConstant.tableParamConfig = tableConfigModel.getTableParamConfig();
				ChildWindowConstant.currentTableNameAndTypes = tableConfigModel.getCurrentTableNameAndTypes();
				ChildWindowConstant.tablesQueryMap = tableConfigModel.getTablesQueryMap();
				ChildWindowConstant.tablesQueryEndAndCnMap = tableConfigModel.getTablesQueryEndAndCnMap();
				ChildWindowConstant.makeEntityModelMap = tableConfigModel.getMakeEntityModelMap();
				ChildWindowConstant.makeEntityEngAndCn = tableConfigModel.getMakeEntityEngAndCn();
				ChildWindowConstant.user1 = tableConfigModel.getUser1();
				ChildWindowConstant.user2 = tableConfigModel.getUser2();
				ChildWindowConstant.user3 = tableConfigModel.getUser3();
				ChildWindowConstant.commonParametersModel = tableConfigModel.getCommonParametersModel();
				ChildWindowConstant.dynamicUserList = tableConfigModel.getDynamicUserList();
				ChildWindowConstant.dataSourceModelMap = tableConfigModel.getDataSourceModelMap();
			}
		} catch (Exception e) {
			JOptionPane.showMessageDialog(null, "读取配置出错（不影响正常使用）！" + e.getMessage(), "警告", JOptionPane.WARNING_MESSAGE);
		}
		return parameters == null ? new Parameters() : parameters;
	}

	/**
	 * 创建新文件
	 *
	 * @param path
	 */
	private static void createFile(String path) throws Exception {
		File file = new File(path);
		if (!file.exists()) {
			if (!file.getParentFile().exists()) {
				new File(file.getParent()).mkdirs();
			}
			file.createNewFile();
		}
	}

	/**
	 * 序列化对象
	 *
	 * @param object
	 * @param path
	 */
	private static void serialization(Object object, String path) throws Exception {
		FileOutputStream outputStream = new FileOutputStream(new File(path));
		ObjectOutputStream out = new ObjectOutputStream(outputStream);
		out.writeObject(object);
		out.close();
	}

	/**
	 * 反序列化对象
	 *
	 * @param path
	 * @param path
	 */
	private static <T> T deserialization(String path) throws Exception {
		File file = new File(path);
		if (!file.exists()) {
			return null;
		}
		FileInputStream inputStream = new FileInputStream(file);
		ObjectInputStream in = new ObjectInputStream(inputStream);
		T obj = CastUtils.cast(in.readObject());
		in.close();
		return obj;
	}

}
